INS
         NLS 
         ORG $AAC1
         OBJ $800
;
SCRATCH  EPZ $27
BOOTSLOT EPZ $2B
ROMRWTS  EPZ $3E
SECNUM   EPZ $3D
OPRND    EPZ $44
BUFADR   EPZ $42
DOSIMG   EPZ $40
IOBADR   EPZ $48
L0478    EQU $478
L04F8    EQU $4F8
L084D    EQU $84D
L08FF    EQU $8FF
L08FE    EQU $8FE
L08FD    EQU $8FD
L090B    EQU $090B
DOSSTRT  EQU $9D84
DOVERIFY EQU $A27D
DOCLOSE  EQU $A2EA
RWC2     EQU $A546
FMDRVR   EQU $A6A8
FMDRVR0  EQU $A6BC
DOERROR  EQU $A6D2
LOCBUF   EQU $A764
KWDRPRMS EQU $A909
CURSTAT  EQU $AA51
CMDINDX  EQU $AA5F
RWTSENT  EQU $BD00
REBOOT   EQU $BFC8
DISKFULL EQU $BFED
MEMTOP   EQU $C000
MONINIT  EQU $FB2F
CLRHOME  EQU $FC58
RDCHAR   EQU $FD0C
PRBYTE   EQU $FDDA
COUT     EQU $FDED
SETKBD   EQU $FE89
SETVID   EQU $FE93
;
;
;
;
; THE FOLLOWING ADDRESSES ARE
; SHARED WITH THE CDI FILE
;
RWTSPADR ADR TBLTYPE
VTOCPADR ADR VTOCSB
DIRPADR  ADR DIRSECBF
         ADR MEMTOP
;
;
; File manager subroutine table.
;
;
FMFTBL   ADR NOERROR-1
         ADR OPNHNDLR-1
         ADR CLSHNDLR-1
         ADR RDHNDLR-1
         ADR WRTHNDLR-1
         ADR DELHNDLR-1
         ADR CATHNDLR-1
         ADR LCKHNDLR-1
         ADR UNLKHNDL-1
         ADR RENHNDLR-1
         ADR POSHNDLR-1
         ADR INITHNDL-1
         ADR VFYHNDLR-1
         ADR NOERROR-1
;
; Read Subcode table.
;
;
FMRSUB   ADR NOERROR-1
         ADR RD1BYTE-1
         ADR RDRANGE-1
         ADR POSRD1B-1
         ADR POSRDR-1
         ADR NOERROR-1
;
; Write subcode table.
;
FMWSUB   ADR NOERROR-1
         ADR WRT1BYTE-1
         ADR WRTRANGE-1
         ADR POSWRT1B-1
         ADR POSWRTR-1
         ADR NOERROR-1
;
;
;
;
; EXTERNAL ENTRY POINT FOR FILE
; MANGER.
;
; X=0, allocate a new file if
; file not found in dir.
;
; X=1, do not allocate a new file
; if file not found.
;
;
;
FMEXT    CPX #0
         BEQ >0
         LDX #2
^0       STX CMDINDX
;
;
;
; NORMAL ENTRY FOR FILE MANAGER
;
;
FILEMNGR TSX 
         STX STKSAVE
;
; GET FM PARMS
;
         JSR LDFMW
;
; CHECK TO SEE IF WE HAVE A VALID
; FM OPCODE..
;
         LDA FMOPCOD
         CMP #$D
         BCS >1
;
; USING OPCODE AS INDEX INTO
; FMFTBL, JMP TO APPROPRIATE
; ROUTINE.
;
         ASL 
         TAX 
         LDA FMFTBL+1,X
         PHA 
         LDA FMFTBL,X
         PHA 
         RTS 
;
;
; JMP TO OPCODE RANGE ERROR
; HANDLER
;
^1       JMP RANGERR
;
;
;
; OPNHNDLR- OPENS A FILE
;
OPNHNDLR JSR CMNOPN
         JMP NOERROR
;
;
; CMNOPN- USED TO OPEN A FILE,
; CALLED BY VARIOUS FILE MANAGER
; ROUTINES.
;
;
;
; INIT FILE MANAGER WORK AREA
;
CMNOPN   JSR INITFMW
;
; SET SECTOR LENGTH TO 256 BYTEST
;
         LDA #$1
         STA SECTLEN+1
;
; IF RECORD LEN = 0, SET TO 1
;
         LDX RECNUM+1
         LDA RECNUM
         BNE >3
         CPX #0
         BNE >3
         INX 
^3       STA OPNRCLEN
         STX OPNRCLEN+1
;
; SEARCH FOR THE FILENAME IN THE
; DIRECTORY, ALLOCATE IF NOT FOUND
;
         JSR LCDIRENT
         BCC PLTSDIR
;
; FILE NOT FOUND IN DIRECTORY,
; SEE IF A FILE IS REQUIRED.
;
         STX DIRINDX
         LDX CMDINDX
         LDA KWDRPRMS,X
         LDX DIRINDX
         LSR 
         BCS >5
;
;
; AT THIS POINT, THE FILE MUST BE
; PRESENT, SEE IF WE ARE LOADING
; APPLESOFT FROM DISK.
;
         LDA CURSTAT
         CMP #$C0
         BNE >4
;
; LOADING AS.  ERROR= LANG NOT AVL
;
         JMP LNOTAVL
;
; LOADING A NORMAL PROGRAM, PRINT
; FILE NOT FOUND.
;
^4       JMP FNOTFND
;
;
; FILE WAS NOT REQUIRED TO BE
; IN THE DIRECTORY, SET IT
; UP
;
;
; SET SECTOR COUNT TO 1
;
^5       LDA #0
         STA FILESIZE+1,X
         LDA #$1
         STA FILESIZE,X
         STX DIRINDX
;
; ALLOCATE A SECTOR FOR T/S LIST
;
         JSR ALLOCSEC
;
; SET UP T/S LIST AND WORK BUFFER
;
         LDX DIRINDX
         STA TSSECTOR,X
         STA FTSS
         STA CURTSS
         LDA SCALAREA+1
         STA TSTRACK,X
         STA FTSTS
         STA CURTSTS
         LDA FILETYPE
         STA FILTYP,X
;
; WRITE DIRECTORY BACK TO DISK
;
         JSR WRTDIRSC
;
; INIT THE WORK BUFFER, DATA
; BUFFER, AND T/S BUFFERS
;
         JSR SELTSBUF
         JSR ZEROBUFR
         JSR SETUPRW
;
; SET RETURN CODE TO FILE NOT FND
;
         LDX DIRINDX
         LDA #6
         STA RTNCODE
;
;
;
; FALL THROUGH FROM ABOVE (FILE
; CREATED AND ENTERED INTO DIR)
;
; -OR- 
;
; COME FROM DIR LOOKUP IF FILE
; WAS FOUND IN DIRECTORY.
;
;
;
; COPY T/S LIST INFO TO WORK 
; BUFFER
;
PLTSDIR  LDA TSTRACK,X
         STA FTSTS
         LDA TSSECTOR,X
         STA FTSS
         LDA FILTYP,X
;
; COPY FILE TYPE TO WORK BUFFER
;
         STA FILETYPE
         STA FTYPE
;
; COPY FILE SIZE TO WORK BUFFER
;
         LDA FILESIZE,X
         STA SECCNT
         LDA FILESIZE+1,X
         STA SECCNT+1
         STX DIRSECIX+1
;
; INIT EOF TO 65535 (INFINITY) 
;
         LDA #$FF
         STA RELSLRD
         STA RELSLRD+1
;
; SET UP # OF ENTRIES IN T/S LIST
;
         LDA NUMTSENT
         STA SECPERTS
;
; READ IN THE FIRST T/S LIST
; (IF THERE IS ONE)
;
         CLC 
         JMP RDTSLIST
;
;
; INITIALIZE FILE MANAGER WORK
; AREA.
;
;
; ZERO OUT T/S LIST
;
INITFMW  LDA #0
         TAX 
^6       STA FTSTS,X
         INX 
         CPX #$2D
         BNE <6
;
; INIT VOLUME # (COMPLIMENTED),
; SLOT, AND DRIVE #.
;
         LDA VOLVAL
         EOR #$FF
         STA VOLNUMBR
         LDA DRVVAL
         STA DRVNUMBR
         LDA SLOTVAL
         ASL 
         ASL 
         ASL 
         ASL 
         TAX 
         STX SLOT16
;
; SET UP FOR DIRECTORY TRACK
;
         LDA #$11
         STA TRKNUMBR
         RTS 
;
;
; CLOSE FILE HANDLER.
;
;
; CHECK TO SEE IF DATA BUFFER OR
; T/S BUFFER NEEDS TO BE WRITTEN
; TO DISK.
;
CLSHNDLR JSR CHKBUF
         JSR CHKTS
;
; RELEASE ANY UNALLOCATED SECTORS
;
         JSR RLSALLC
;
; CHECK TO SEE IF FILE SIZE
; HAS CHANGED.
;
         LDA #2
         AND FLAGS
         BEQ >7
;
; IF SO, READ VTOC, UPDATE IT,
; READ DIR, AND UPDATE FILE SIZE
;
         JSR RWVTOC
         LDA #0
         CLC 
^6       JSR RDDIRSEC
         SEC 
         DEC DIRSECIX
         BNE <6
         LDX DIRSECIX+1
         LDA SECCNT
         STA FILESIZE,X
         LDA SECCNT+1
         STA FILESIZE+1,X
         JSR WRTDIRSC
;
; NORMAL CLOSE EXIT PT.
;
^7       JMP NOERROR
;
;
; RENAME HANDLER.
;
RENHNDLR JSR CMNOPN          ;LOOKUP FILE
;
; SEE IF THE FILE IS LOCKED
;
         LDA FTYPE
         BMI FILOCKED
;
;
; IF NOT, POINT BUFADR AT THE
; SECOND FILENAME AND COPY IT
; INTO THE DIRECTORY
;
         LDA RECNUM
         STA BUFADR
         LDA RECNUM+1
         STA BUFADR+1
         LDX DIRINDX
         JSR COPYFNAM
;
; WRITE THE DIRECTORY BACK TO
; DISK
;
         JSR WRTDIRSC
         JMP NOERROR
;
;
; READ FUNCTION HANDLER.
;
RDHNDLR  LDA SUBCODE
;
; MAKE SURE SUBCODE IS < 5
;
         CMP #5
         BCS >8
;
; USE SUBCODE AS INDEX INTO FMRSUB
; TABLE, JUMP TO THAT ADDRESS
;
         ASL 
         TAX 
         LDA FMRSUB+1,X
         PHA 
         LDA FMRSUB,X
         PHA 
         RTS 
^8       JMP RANGERR2
;
; ERROR EXIT POINT IF THE
; FILE WAS LOCKED
;
FILOCKED JMP FILELOCK
;
;
; WRITE FUNCTION HANDLER.
;
;
; MAKE SURE THE FILE IS NOT LOCKED
;
WRTHNDLR LDA FTYPE
         BMI FILOCKED
;
; CHECK SUBCODE (< 5)
;
         LDA SUBCODE
         CMP #5
         BCS <8
;
; USE SUBCODE AS INDEX INTO
; FMWSUB TABLE
;
         ASL 
         TAX 
         LDA FMWSUB+1,X
         PHA 
         LDA FMWSUB,X
         PHA 
         RTS 
;
;
; POSITION AND READ 1 BYTE HANDLER
;
; (POSITIONS AND DROPS THROUGH TO
; READ ONE BYTE)
;
POSRD1B  JSR CALPOSN
;
; READ ONE BYTE ROUTINE
;
RD1BYTE  JSR RDABYTE
         STA DATABYTE
         JMP NOERROR
;
;
; POSITION AND READ A RANGE OF
; BYTES
;
POSRDR   JSR CALPOSN
;
; READ A RANGE OF BYTES
;
RDRANGE  JSR DECRNG
         JSR RDABYTE
         PHA 
         JSR MOVRANG
         LDY #0
         PLA 
         STA (BUFADR),Y
         JMP RDRANGE
;
;
; RDABYTE READS A DATA BYTE FROM
; THE FILE, READING IN ADDITIONAL
; SECTORS AS NECESSARY.
;
RDABYTE  JSR RDNXTDA
         BCS >9
         LDA (BUFADR),Y
         PHA 
         JSR INCREC
         JSR INCPOS
         PLA 
         RTS 
^9       JMP ENDATA
;
;
; POSITION AND WRITE ONE BYTE
; HANDLER.
;
POSWRT1B JSR CALPOSN
;
;
; WRITE ONE BYTE HANDLER
;
WRT1BYTE LDA DATABYTE
         JSR WRTBYTE
         JMP NOERROR
;
; POSITION AND WRITE RANGE
;
POSWRTR  JSR CALPOSN
;
;
; WRITE A RANGE OF BYTES
;
WRTRANGE JSR MOVRANG
         LDY #0
         LDA (BUFADR),Y
         JSR WRTBYTE
         JSR DECRNG
         JMP WRTRANGE
;
;
; WRITE A SINGLE BYTE TO A FILE
;
WRTBYTE  PHA 
         JSR RDNXTDA
         PLA 
         STA (BUFADR),Y
         LDA #$40
         ORA FLAGS
         STA FLAGS
         JSR INCREC
         JMP INCPOS
;
;
; LOCK FUNCTION HANDLER
;
LCKHNDLR LDA #$80
         STA ALLCFLG
         BNE >0
;
;
; UNLOCK FUNCTION HANDLER
;
UNLKHNDL LDA #0
         STA ALLCFLG
^0       JSR CMNOPN
         LDX DIRINDX
         LDA FILTYP,X
         AND #$7F
         ORA ALLCFLG
         STA FILTYP,X
         JSR WRTDIRSC
^1       JMP NOERROR
;
;
; POSITION FUNCTION HANDLER
;
POSHNDLR JSR CALPOSN
         JMP NOERROR
;
;
; VERIFY HANDLER
;
VFYHNDLR JSR CMNOPN
;
; READ UNTIL EOF
;
^2       JSR RDNXTDA
         BCS <1
         INC FILEPOSN
         BNE <2
         INC FILEPOSN+1
         JMP <2
;
;
; DELETE HANDLER
;
DELHNDLR JSR CMNOPN
;
; SEE IF THE FILE IS LOCKED
;
         LDX DIRINDX
         LDA FILTYP,X
         BPL >3
         JMP FILELOCK
;
; IF THE FILE IS NOT LOCKED,
; COPY THE T/S LIST POINTER
; AND PUT $FF IN THE OLD
; T/S LIST POINTER SPOT
;
^3       LDX DIRINDX
         LDA TSTRACK,X
         STA FTSTS
         STA FILESIZE-1,X
         LDA #$FF
         STA TSTRACK,X
         LDY TSSECTOR,X
         STY FTSS
;
; WRITE DIRECTORY BACK TO DISK
;
         JSR WRTDIRSC
;
; READ THE T/S LIST SECTORS AND
; UPDATE VTOC UNTIL THERE ARE
; NO MORE T/S SECTORS
;
         CLC 
RDNXTTS  JSR RDTSLIST
         BCS >6
         JSR SELTSBUF
         LDY #$C
^4       STY DIRINDX
         LDA (BUFADR),Y
;
; IF TRACK NUMBER IS ZERO OR
; MINUS, SKIP IT
;
         BMI >5
         BEQ >5
;
; OTHERWISE UPDATE VTOC
;
         PHA 
         INY 
         LDA (BUFADR),Y
         TAY 
         PLA 
         JSR FREESECT
;
; GET NEXT T/S PAIR
;
^5       LDY DIRINDX
         INY 
         INY 
         BNE <4
;
; IF AT END OF T/S SECTOR, FREE
; THE SECTOR IT USES AND TRY
; TO GET THE NEXT SECTOR
;
         LDA CURTSTS
         LDY CURTSS
         JSR FREESECT
         SEC 
         BCS RDNXTTS
^6       JSR WRTVTOC
         JMP NOERROR
;
;
; FREESECT, DEALLOCATES A SECTOR
; IN THE TRACK BIT MAP
;
FREESECT SEC 
         JSR RORBITMP
         LDA #0
         LDX #5
^7       STA SCALAREA,X
         DEX 
         BPL <7
         RTS 
;
;
;
; CATALOG HANDLER
;
CATHNDLR JSR INITFMW
;
; ALLOW ANY VOLUME OF DISK
; ($FF COMPLIMENTED = VOL 0)
;
         LDA #$FF
         STA VOLNUMBR
;
; READ VTOC TO FIND OUT WHERE
; THE CATALOG IS
;
         JSR RWVTOC
;
; SET UP COUNTER TO STOP EVERY 22
; LINES
;
         LDA #$16
         STA CNTR
;
;
; SKIP TWO LINES AND PRINT
; "DISK VOLUME"
;
         JSR SKIPLN
         JSR SKIPLN
         LDX #$B
^8       LDA DISKVOL,X
         JSR COUT
         DEX 
         BPL <8
;
; PRINT THE VOLUME NUMBER
;
         STX OPRND+1
         LDA VOLFND
         STA OPRND
         JSR PRTDEC
         JSR SKIPLN
         JSR SKIPLN
;
;
;  PRINT ALL THE DIRECTORY ENTRIES
;
         CLC 
RDNXTDIR JSR RDDIRSEC
         BCS DONEXT2
         LDX #0
GTRKNUM  STX DIRINDX
         LDA TSTRACK,X
;
; IF TRACK BYTE IS ZERO, END OF
; DIRECTORY HAS BEEN REACHED,
; IF MINUS, FILE WAS DELETED AND
; SHOULD NOT BE LISTED.
;
         BEQ DONEXT2
         BMI DONEXT
;
; SEE IF THE FILE IS LOCKED
;
         LDY #" "
         LDA FILTYP,X
         BPL >9
         LDY #"*"
^9       TYA 
         JSR COUT
;
;
; OUTPUT FILE TYPE
;
         LDA FILTYP,X
         AND #$7F
         LDY #7
         ASL 
^0       ASL 
         BCS >1
         DEY 
         BNE <0
^1       LDA FTTBL,Y
         JSR COUT
         LDA #$A0
         JSR COUT
;
; OUTPUT FILE SIZE
;
         LDA FILESIZE,X
         STA OPRND
         LDA FILESIZE+1,X
         STA OPRND+1
         JSR PRTDEC
         LDA #$A0
         JSR COUT
         INX 
         INX 
         INX 
;
; OUTPUT FILE NAME
;
         LDY #$1D
^2       LDA TSTRACK,X
         JSR COUT
         INX 
         DEY 
         BPL <2
         JSR SKIPLN
;
; GET NEXT DIR ENTRY (READING A
; DIR SECTOR IF REQ'D)
;
DONEXT   JSR NXTDIREN
         BCC GTRKNUM
         BCS RDNXTDIR
;
; DIR ALL DONE
;
DONEXT2  JMP NOERROR
;
; SKIPLN- PRINTS A <CR> AND
; CHECKS TO SEE IF THE CNTR
; HAS BECOME ZERO OR NOT
;
SKIPLN   LDA #$8D
         JSR COUT
         DEC CNTR
         BNE >3
         JSR RDCHAR
         LDA #$15
         STA CNTR
^3       RTS 
;
;
; PRTDEC- PRINTS (OPRAND,OPRAND+1)
; AS A DECIMAL INTEGER.
;
PRTDEC   LDY #2
PRTDEC2  LDA #0
         PHA 
^4       LDA OPRND
         CMP DECTBL,Y
         BCC >5
         SBC DECTBL,Y
         STA OPRND
         LDA OPRND+1
         SBC #0
         STA OPRND+1
         PLA 
         ADC #0
         PHA 
         JMP <4
^5       PLA 
         ORA #$B0
         JSR COUT
         DEY 
         BPL PRTDEC2
         RTS 
;
;
; LOAD FILE MANAGER WORK AREA
; FROM THE FILE BUFFER.
;
LDFMW    JSR SELBUF
         LDY #0
         STY RTNCODE
^6       LDA (BUFADR),Y
         STA FTSTS,Y
         INY 
         CPY #$2D
         BNE <6
         CLC 
         RTS 
;
; SAVE FILE MANAGER WORK AREA INTO
; FILE BUFFER
;
SAVFMW   JSR SELBUF
         LDY #0
^9       LDA FTSTS,Y
         STA (BUFADR),Y
         INY 
         CPY #$2D
         BNE <9
         RTS 
;
;
; INIT FUNCTION HANDLER.
;
INITHNDL JSR INITFMW
         LDA #4
;
;
; INIT VTOC INFO
;
         JSR SETCMDCD
;
; Volume # must be complimented.
;
         LDA VOLNUMBR
         EOR #$FF
         STA DSKVOL
;
; Set up next track to allocate
; at track 17.
;
         LDA #$11
         STA NXTTOALC
;
; Allocate sectors in positive
; direction (from $11 up).
;
         LDA #$1
         STA ALLCDIR
;
; Mark the "possible" 56 tracks
; as all being used.
;
         LDX #$38
         LDA #0
^0       STA VTOCSB,X
         INX 
         BNE <0
;
; Mark the Apple's 35 tracks as
; unused.
;
; Track 0 is not marked as unused
;
;
         LDX #$C
^1       CPX #$8C
         BEQ >3
         LDY #3
^2       LDA FREEMASK,Y
         STA BITMAP,X
         INX 
         DEY 
         BPL <2
         CPX #$44
         BNE <1
         LDX #$48
         BNE <1
^3       JSR WRTVTOC
;
; INIT DIRECTORY INFO
;
         LDX #0
         TXA 
^4       STA DIRSECBF,X
         INX 
         BNE <4
         JSR PRWTSDIR
;
; Set up for directory track
;
         LDA #$11
;
; Set up for dir sector.
;
         LDY NUMSCTRS
         DEY 
         DEY 
         STA TNUM
;
; Write directory sectors out to
; disk.
;
^5       STA TSNXTDIR
^6       STY TSNXTDIR+1
         INY 
         STY SNUM
         LDA #2
         JSR SETCMDCD
         LDY TSNXTDIR+1
         DEY 
         BMI >7
         BNE <6
         TYA 
         BEQ <5
^7       JSR RWTSPRMS
;
; WRITE DOS OUT TO DISK
;
         JSR PUTDOS
         JMP NOERROR
;
;
; SELECT A BUFFER,
;
; FILE MANAGER WORK BUFFER
;
SELBUF   LDX #0
         BEQ >8
;
; SELECT T/S LIST BUFFER
;
SELTSBUF LDX #2
         BNE >8
;
;
; SELECT DATA BUFFER
;
SELDABUF LDX #4
^8       LDA WBADR,X
         STA BUFADR
         LDA WBADR+1,X
         STA BUFADR+1
         RTS 
;
;
; CHECK DATA BUFFER TO SEE IF IT
; NEEDS TO BE WRITTEN TO DISK
;
CHKBUF   BIT FLAGS
         BVS >9
         RTS 
^9       JSR PREPDATA
         LDA #2
         JSR RWTSDRVR
         LDA #$BF
         AND FLAGS
         STA FLAGS
         RTS 
;
;
; CHECK T/S LIST BUFFER TO SEE
; IF IT MUST BE WRITTEN TO DISK
;
CHKTS    LDA FLAGS
         BMI SETUPRW
         RTS 
SETUPRW  JSR PREPRWTS
         LDA #2
         JSR RWTSDRVR
         LDA #$7F
         AND FLAGS
         STA FLAGS
         RTS 
;
;
; SET UP IOB FOR RWTS CALL
;
PREPRWTS LDA TSLSTADR
         STA USRBUF
         LDA TSLSTADR+1
         STA USRBUF+1
         LDX CURTSTS
         LDY CURTSS
         RTS 
;
;
; READ A T/S LIST INTO THE FILE
; BUFFER.
;
; ON ENTRY C=0 IF FIRST T/S SECTOR
; IS DESIRED, C=1 IF THE NEXT
; T/S SECTOR IS DESIRED.
;
RDTSLIST PHP 
;
; First, check to see if the
; current T/S list must be
; written to disk.
;
         JSR CHKTS
         JSR PREPRWTS
         JSR SELTSBUF
         PLP 
         BCS >9
;
; If the carry flag is cleared,
; read the first sector of the
; T/S list.
;
         LDX FTSTS
         LDY FTSS
         JMP OLDRWTS
;
; If the carry flag was set read
; in the next sector of the
; T/S list.
;
^9       LDY #$1
;
; If the track number of the next
; sector is zero, there isn't
; another T/S sector available.
;
         LDA (BUFADR),Y
         BEQ >0
;
; If there is another T/S list
; available read it in.
;
         TAX 
         INY 
         LDA (BUFADR),Y
         TAY 
         JMP OLDRWTS
;
; If the File Manager Opcode is
; isn't write, exit with error
; status passed in carry.
;
^0       LDA FMOPCOD
         CMP #4
         BEQ >1
         SEC 
         RTS 
;
; If writing to disk, simply
; allocate another sector for
; the T/S list and continue.
;
^1       JSR ALLOCSEC
         LDY #2
         STA (BUFADR),Y
         PHA 
         DEY 
         LDA SCALAREA+1
         STA (BUFADR),Y
         PHA 
         JSR SETUPRW
         JSR ZEROBUFR
         LDY #5
         LDA RELSLAST
         STA (BUFADR),Y
         INY 
         LDA RELSLAST+1
         STA (BUFADR),Y
         PLA 
         TAX 
         PLA 
         TAY 
         LDA #2
         BNE >0
;
; If Acc=1, read old T/S list.
; If Acc=2, write new sector for
; T/S list.
;
OLDRWTS  LDA #$1
^0       STX CURTSTS
         STY CURTSS
         JSR RWTSDRVR
;
; Compute relative sector number
; of the last sector represented
; in this T/S list and store
; in workarea.
;
         LDY #5
         LDA (BUFADR),Y
         STA RELSFRST
         CLC 
         ADC SECPERTS
         STA RELSLAST
         INY 
         LDA (BUFADR),Y
         STA RELSFRST+1
         ADC SECPERTS+1
         STA RELSLAST+1
         CLC 
         RTS 
;
;
; READ A DATA SECTOR
;
RDDASEC  JSR PREPDATA
         LDA #$1
         JMP RWTSDRVR
;
; PREP RWTS' IOB FOR READING
; A DATA SECTOR.
;
PREPDATA LDY DATASADR
         LDA DATASADR+1
         STY USRBUF
         STA USRBUF+1
         LDX CURDATS
         LDY CURDAS
         RTS 
;
;
; READ OR WRITE THE VTOC
;
RWVTOC   LDA #$1
         BNE >1
WRTVTOC  LDA #2
^1       LDY VTOCPADR
         STY USRBUF
         LDY VTOCPADR+1
         STY USRBUF+1
         LDX TRKNUMBR
         LDY #0
         JMP RWTSDRVR
;
;
; READ A DIRECTORY SECTOR
;
; If C=0 read first dir sector.
; If C=1 read next dir sector.
;
;
RDDIRSEC PHP 
         JSR PRWTSDIR
         PLP 
         BCS >2
;
; Read first directory sector here
;
         LDY FRSTTS+1
         LDX FRSTTS
         BNE >4
^2       LDX TSNXTDIR
         BNE >3
;
;
; If there are no more dir
; sectors, exit with error flag
; (carry) set.
;
         SEC 
         RTS 
;
; Read next dir sector in chain
; here.
;
^3       LDY TSNXTDIR+1
^4       STX DIRTS
         STY DIRTS+1
         LDA #$1
         JSR RWTSDRVR
         CLC 
         RTS 
;
; WRITE A DIRECTORY SECTOR
;
WRTDIRSC JSR PRWTSDIR
         LDX DIRTS
         LDY DIRTS+1
         LDA #2
         JMP RWTSDRVR
;
;
; PREP RWTS FOR DIRECTORY READ/WRT
;
PRWTSDIR LDA DIRPADR
         STA USRBUF
         LDA DIRPADR+1
         STA USRBUF+1
         RTS 
;
; RWTS DRIVER, FINISHES UP THE IOB
; AND CALLS THE RWTS ROUTINE
;
RWTSDRVR STX TNUM
         STY SNUM
SETCMDCD STA CMDCODE
         CMP #2
         BNE >4
;
; If writing to disk, note this
; in "FLAGS".
;
         ORA FLAGS
         STA FLAGS
;
; Compliment the volume number
;
^4       LDA VOLNUMBR
         EOR #$FF
         STA VOLEXPT
;
; Init such niceties as slot,
; drive, sector, etc.
;
         LDA SLOT16
         STA SNUM16
         LDA DRVNUMBR
         STA DNUM
         LDA SECTLEN
         STA BYTCNT
         LDA SECTLEN+1
         STA BYTCNT+1
         LDA #$1
         STA TBLTYPE
;
; Call the RWTS subroutine
;
         LDY RWTSPADR
         LDA RWTSPADR+1
         JSR CALLRWTS
;
; Fiddle with the volume numbers
; before checking for an error
;
;
         LDA VOLFND
         STA VOLVAL
         LDA #$FF
         STA VOLEXPT
;
; If no error, quit
;
         BCS >5
         RTS 
;
;
; Convert RWTS error # to an
; error number usable by the
; file manager.
;
^5       LDA ERRRCODE
         LDY #7
         CMP #$20
         BEQ >6
         LDY #4
         CMP #$10
         BEQ >6
         LDY #8
^6       TYA 
         JMP SETERROR
;
;
; READ NEXT DATA SECTOR IF REQ'D
;
;
; Check to see if the current file
; position is in the current data
; sector buffered up in memory.
;
RDNXTDA  LDA FILEPOSN
         CMP RELSLRD
         BNE >7
         LDA FILEPOSN+1
         CMP RELSLRD+1
         BEQ SLDBUF2
;
; If not, see if the current
; sector needs to be written to
; disk.
;
^7       JSR CHKBUF
;
;
; Is the desired file position
; within the range of sectors
; represented by the T/S list
; currently buffered in memory?
;
^8       LDA FILEPOSN+1
         CMP RELSFRST+1
         BCC >0              ;go if <
         BNE >9              ;go if >
         LDA FILEPOSN
         CMP RELSFRST
         BCC >0
;
^9       LDA FILEPOSN+1
         CMP RELSLAST+1
         BCC FNDTS
         BNE >0
         LDA FILEPOSN
         CMP RELSLAST
         BCC FNDTS
;
; Read in new T/S list, Carry is
; set or cleared from CMP's above.
;
;
^0       JSR RDTSLIST
         BCC <8
         RTS 
;
; DATA WAS FOUND IN CURRENT T/S
; LIST, GET ENTRY IN THIS T/S LIST
;
FNDTS    SEC 
         LDA FILEPOSN
         SBC RELSFRST
         ASL 
         ADC #$C
         TAY 
         JSR SELTSBUF
         LDA (BUFADR),Y
         BNE READOLD
         LDA FMOPCOD
         CMP #4
         BEQ >1
         SEC 
         RTS 
^1       JSR ADDATA
         JMP SAVSECNM
;
; READ EXISTING DATA USING CURRENT
; T/S LIST
;
READOLD  STA CURDATS
         INY 
         LDA (BUFADR),Y
         STA CURDAS
         JSR RDDASEC
;
; SAVE SECTOR NUMBER OF SECTOR
; LAST READ IN THE WORKAREA
;
SAVSECNM LDA FILEPOSN
         STA RELSLRD
         LDA FILEPOSN+1
         STA RELSLRD+1
;
;
; SELECT DATA BUFFER
;
SLDBUF2  JSR SELDABUF
         LDY FILEPOSN+2
         CLC 
         RTS 
;
; ADD A NEW DATA SECTOR TO THE
; FILE
;
ADDATA   STY CNTR
;
; Allocate a sector for the data.
;
         JSR ALLOCSEC
;
; Put T/S numbers into T/S list.
;
         LDY CNTR
         INY 
         STA (BUFADR),Y
         STA CURDAS
         DEY 
         LDA SCALAREA+1
         STA (BUFADR),Y
         STA CURDATS
;
; Select data buffer and zero it
; out.
;
         JSR SELDABUF
         JSR ZEROBUFR
;
; set up flags noting that the
; current data and T/S sectors
; must be written to disk.
;
         LDA #$C0
         ORA FLAGS
         STA FLAGS
         RTS 
;
;
;:
;
;
; VARIOUS UTILITIES USED ALL OVER
; THE PLACE
;
;
; INCREMENT RECORD NUMBER AND
; BYTE OFFSET INTO THE FILE
;
INCREC   LDX RECNUMBR
         STX RECNUM
         LDX RECNUMBR+1
         STX RECNUM+1
         LDX BYTEOFFS
         LDY BYTEOFFS+1
         STX VOLVAL
         STY DRVVAL
         INX 
         BNE >3
         INY 
^3       CPY OPNRCLEN+1
         BNE >4
         CPX OPNRCLEN
         BNE >4
         LDX #0
         LDY #0
         INC RECNUMBR
         BNE >4
         INC RECNUMBR+1
^4       STX BYTEOFFS
         STY BYTEOFFS+1
         RTS 
;
;
; INCREMENT FILE POSITION
; OFFSET
;
INCPOS   INC FILEPOSN+2
         BNE >5
         INC FILEPOSN
         BNE >5
         INC FILEPOSN+1
^5       RTS 
;
;
; COPY AND ADVANCE RANGE ADDRESS
;
MOVRANG  LDY DATABYTE
         LDX DATABYTE+1
         STY BUFADR
         STX BUFADR+1
         INC DATABYTE
         BNE >6
         INC DATABYTE+1
^6       RTS 
;
; DECREMENT RANGE ADDRESS
;
DECRNG   LDY SLOTVAL
         BNE >7
         LDX FILETYPE
         BEQ >8
         DEC FILETYPE
^7       DEC SLOTVAL
         RTS 
^8       JMP NOERROR
;
;
; LOCATE A DIRECTORY ENTRY.
; LOOKS UP A FILENAME IN THE
; DIRECTORY.
;
;
; Read VTOC to get track and
; sector number of first dir
; sector.
;
LCDIRENT JSR RWVTOC
         LDA FNADR
         STA BUFADR
         LDA FNADR+1
         STA BUFADR+1
;
; Set up for two passes through
; the directory.
;
         LDA #$1
INITDIR  STA CNTR
;
; Set up index into VTOC for
; the dir track.
;
         LDA #0
         STA DIRSECIX
         CLC 
;
; Read in the current dir sector.
;
INCSECOF INC DIRSECIX
         JSR RDDIRSEC
         BCS PASS2
;
; Check for end of dir (if first
; byte is zero) or a deleted
; file (if minus, really should
; be $FF).
;
         LDX #0
GETRACK  STX DIRINDX
         LDA TSTRACK,X
         BEQ DOPASS2
         BMI CHKPASS
         LDY #0
         INX 
         INX 
;
;  Compare the filename against
; the current dir entry.
;
^8       INX 
         LDA (BUFADR),Y
         CMP TSTRACK,X
         BNE >9
         INY 
         CPY #$1E
         BNE <8
;
; If found, return with index
; into sector in the X register
; and the carry flag cleared.
;
         LDX DIRINDX
         CLC 
         RTS 
;
;
; If filename doesn't match
; current entry, on to the next 1.
;
^9       JSR NXTDIREN
         BCC GETRACK
         BCS INCSECOF
DOPASS2  LDY CNTR
         BNE INITDIR
CHKPASS  LDY CNTR
         BNE <9
;
;
; COPY FILE NAME TO DIRECTORY
; ENTRY.
;
COPYFNAM LDY #0
         INX 
         INX 
^0       INX 
         LDA (BUFADR),Y
         STA TSTRACK,X
         INY 
         CPY #$1E
         BNE <0
         LDX DIRINDX
         SEC 
         RTS 
;
; MOVE ON TO THE NEXT DIRECTORY
; ENTRY.
;
NXTDIREN CLC 
         LDA DIRINDX
         ADC #$23
         TAX 
         CPX #$F5
         RTS 
PASS2    LDA #0
         LDY CNTR
         BNE INITDIR
         JMP DSKFULL
;
;
;
; ALLOCATE A DISK SECTOR.
;
; This routine finds a track in
; the track bit map stored in
; memory that has some empty
; sectors left.
;  ALLOCSEC then allocates the
; rest of those sectors and
; gives them to the requesting
; file.
;
;
;
; First, see if there is a
; track already allocated to this
; file.
;
ALLOCSEC LDA SCALAREA+1
         BEQ NOTRKAVL
;
; If so, decrement sector count
; to find the next possible
; sector #.
;
TSTNXT   DEC SCALAREA
         BMI NOSECAVL
;
; If a valid sector, rotate the
; bit map to see if it is free.
;
         CLC 
         LDX #4
^1       ROL SCALAREA+1,X
         DEX 
         BNE <1
;
; If not free, repeat for next
; sector.
;
         BCC TSTNXT
;
; If free, allocate and increment
; file size by one.
;
         INC SECCNT
         BNE >2
         INC SECCNT+1
^2       LDA SCALAREA
         RTS 
;
;
; Indicate that a track is not
; currently allocated.
;
NOSECAVL LDA #0
         STA SCALAREA+1
;
; Reset allocation flag to
; allow a complete scan of the
; bit map for available sectors.
;
NOTRKAVL LDA #0
         STA ALLCFLG
         JSR RWVTOC
;
; Add allocation director to
; NXTTOALLC and see if we are
; at track zero, or past
; track 34.
;
ADDIRCTN CLC 
         LDA NXTTOALC
         ADC ALLCDIR
         BEQ SCNDTIME
         CMP NUMTRKS
         BCC >3
;
; If past track 34, set allocation
; direction to -1.
;
         LDA #$FF
         BNE ATDIRTRK
SCNDTIME LDA ALLCFLG
         BNE DODSKFUL
         LDA #$1
         STA ALLCFLG
;
; Start at the dir track and
; work backwards.
;
ATDIRTRK STA ALLCDIR
         CLC 
         ADC #$11
^3       STA NXTTOALC
         STA SCALAREA+1
         TAY 
         ASL 
         ASL 
         TAY 
         LDX #4
         CLC 
^4       LDA BTMPEND,Y
         STA SCALAREA+1,X
         BEQ >5
         SEC 
         LDA #0
         STA BTMPEND,Y
^5       DEY 
         DEX 
         BNE <4
         BCC ADDIRCTN
;
; Allocated an entire track,
; write out the VTOC so other
; files don't use 'em
;
         JSR WRTVTOC
         LDA NUMSCTRS
         STA SCALAREA
         BNE TSTNXT
DODSKFUL JMP DSKFULL
;
;
; RELEASE ANY ALLOCATED SECTORS
; THAT WERE NOT USED.
;
RLSALLC  LDA SCALAREA+1
         BNE >6
         RTS 
^6       PHA 
         JSR RWVTOC
         LDY SCALAREA
         PLA 
         CLC 
         JSR RORBITMP
         LDA #0
         STA SCALAREA+1
         JMP WRTVTOC
;
;
; ROTATE THE BIT MAP RIGHT ONE
; BIT.
; THIS CHECKS FOR AVAILABLE SECS
;
;
RORBITMP LDX #$FC
^7       ROR TMPBITMP,X
         INX 
         BNE <7
         INY 
         CPY NUMSCTRS
         BNE RORBITMP
         ASL 
         ASL 
         TAY 
         BEQ >9
         LDX #4
^8       LDA SCALAREA+1,X
         ORA BTMPEND,Y
         STA BTMPEND,Y
         DEY 
         DEX 
         BNE <8
^9       RTS 
;
;
; CALCULATE FILE POSITION.
;
; GIVEN A RECORD NUMBER, A FILE
; LENGTH, AND A BYTE OFFSET THIS
; ROUTINE CALCULATES THE OFFSET
; INTO THE FILE TO FIND THE
; DESIRED RECORD.
;
CALPOSN  LDA RECNUM
         STA FILEPOSN+2
         STA RECNUMBR
         LDA RECNUM+1
         STA FILEPOSN
         STA RECNUMBR+1
         LDA #0
         STA FILEPOSN+1
         LDY #$10
^0       TAX 
         LDA FILEPOSN+2
         LSR 
         BCS >1
         TXA 
         BCC >2
^1       CLC 
         LDA FILEPOSN+1
         ADC OPNRCLEN
         STA FILEPOSN+1
         TXA 
         ADC OPNRCLEN+1
^2       ROR 
         ROR FILEPOSN+1
         ROR FILEPOSN
         ROR FILEPOSN+2
         DEY 
         BNE <0
         LDA VOLVAL
         STA BYTEOFFS
         ADC FILEPOSN+2
         STA FILEPOSN+2
         LDA DRVVAL
         STA BYTEOFFS+1
         ADC FILEPOSN
         STA FILEPOSN
         LDA #0
         ADC FILEPOSN+1
         STA FILEPOSN+1
         RTS 
;
;
; MULTIPLY CALLED ERROR MESSAGES
;
LNOTAVL  LDA #$1
         BNE SETERROR
RANGERR  LDA #2
         BNE SETERROR
RANGERR2 LDA #3
         BNE SETERROR
         LDA #4
         BNE SETERROR
ENDATA   LDA #5
         BNE SETERROR
FNOTFND  LDA #6
         BNE SETERROR
DSKFULL  JMP DISKFULL
         NOP 
FILELOCK LDA #$A
         BNE SETERROR
NOERROR  LDA RTNCODE
         CLC 
         BCC >3
;
; STANDARD ERROR ENTRY POINT
;
SETERROR SEC 
^3       PHP 
         STA RTNCODE
         LDA #0
         STA IOBADR
         JSR SAVFMW
         PLP 
         LDX STKSAVE
         TXS 
         RTS 
;
;
; VARIABLES ETC.
;
DIRTS    DFS 2
LB399    DFS 2
STKSAVE  DFS 1
DIRINDX  DFS 1
CNTR     DFS 1
ALLCFLG  DFS 2
FREEMASK DFS 4
DECTBL   HEX 010A64
FTTBL    ASC "TIABSRAB"
DISKVOL  ASC " EMULOV KSID"
VTOCSB   DFS 1
FRSTTS   DFS 2
DOSRLS   HEX 03
         DFS 2
DSKVOL   DFS $21
NUMTSENT DFS 9
NXTTOALC DFS 1
ALLCDIR  DFS 3
NUMTRKS  DFS 1
NUMSCTRS DFS 3
BITMAP   DFS 3
BTMPEND  DFS $C5
DIRSECBF DFS 1
TSNXTDIR DFS 10
TSTRACK  DFS 1
TSSECTOR DFS 1
FILTYP   DFS $1F
FILESIZE DFS $F
TMPBITMP DFS $AE
LB5A4    DFS $17
;
;
;
FMOPCOD  DFS 1
SUBCODE  DFS 1
RECNUM   DFS 2
VOLVAL   DFS 1
DRVVAL   DFS 1
SLOTVAL  DFS 1
FILETYPE DFS 1
DATABYTE:
FNADR    DFS 2
RTNCODE  DFS 2
WBADR    DFS 2
TSLSTADR DFS 2
DATASADR DFS 2
         DFS 4
FTSTS    DFS 1
FTSS     DFS 1
CURTSTS  DFS 1
CURTSS   DFS 1
FLAGS    DFS 1
CURDATS  DFS 1
CURDAS   DFS 1
DIRSECIX DFS 2
SECPERTS DFS 2
RELSFRST DFS 2
RELSLAST DFS 2
RELSLRD  DFS 2
SECTLEN  DFS 2
FILEPOSN DFS 3
         DFS 1
OPNRCLEN DFS 2
RECNUMBR DFS 2
BYTEOFFS DFS 2
SECCNT   DFS 2
SCALAREA DFS 1
         DFS 5
FTYPE    DFS 1
SLOT16   DFS 1
DRVNUMBR DFS 1
VOLNUMBR DFS 1
TRKNUMBR DFS 6
;
;
;
; START OF 2ND STAGE BOOTSTRAP
;
BOOT     HEX 01
         LDA SCRATCH
         CMP #9
         BNE >0
         LDA BOOTSLOT
         LSR 
         LSR 
         LSR 
         LSR 
         ORA #$C0
         STA ROMRWTS+1
         LDA #$5C
         STA ROMRWTS
         CLC 
         LDA L08FE
         ADC L08FF
         STA L08FE
^0       LDX L08FF
         BMI >1
         LDA L084D,X
         STA SECNUM
         DEC L08FF
         LDA L08FE
         STA SCRATCH
         DEC L08FE
         LDX BOOTSLOT
         JMP (ROMRWTS)
^1       INC L08FE
         INC L08FE
         JSR SETKBD
         JSR SETVID
         JSR MONINIT
         LDX BOOTSLOT
         JMP (L08FD)
;
;
         HEX 000D0B0907
         HEX 0D03010E
         HEX 0C
         HEX 0A080604
         HEX 02
         HEX 0F
;
;
; THE FOLLOWING ARE ALL PATCHES
; FOR APPEND AND VERIFY
;
;
APPFLG   BYT 0
APNDPTCH JSR LOCBUF
         BCS >0
         LDA #0
         TAY 
         STA APPFLG
         STA (DOSIMG),Y
^0       LDA RTNCODE
         JMP DOERROR
         LDA APPFLG
         BEQ >3
         INC RECNUM
         BNE >3
         INC RECNUM+1
^3       LDA #0
         STA APPFLG
         JMP RWC2
         STA SUBCODE
         JSR FMDRVR
         JSR DOCLOSE
         JMP DOVERIFY
         LDY #$13
^4       LDA (BUFADR),Y
         BNE >7
         INY 
         CPY #$17
         BNE <4
         LDY #$19
^5       LDA (BUFADR),Y
         STA LB5A4,Y
         INY 
         CPY #$1D
         BNE <5
^6       JMP FMDRVR0
^7       LDX #$FF
         STX APPFLG
         BNE <6
;
;
         DFS 19,0
         DFS 24,0
         DFS 32,0
;
FRSTPAG  HEX B6
;
;
;
;
; DOS SECOND STAGE BOOT PGM
;
NUMSECS  HEX 09
         STX SNUM16
         STX SLOTFND
         LDA #$1
         STA DRVFND
         STA DNUM
         LDA NUMPGS
         STA NSECSRW
         LDA #2
         STA TNUM
         LDA #4
         STA SNUM
         LDY FRSTBOOT+1
         DEY 
         STY USRBUF+1
         LDA #$1
         STA CMDCODE
         TXA 
         LSR 
         LSR 
         LSR 
         LSR 
         TAX 
         LDA #0
         STA L04F8,X
         STA L0478,X
         JSR RWPAGES
         LDX #$FF
         TXS 
         STX VOLEXPT
         JMP REBOOT
         JSR SETKBD
         JMP DOSSTRT
;
;
; PUTDOS- WRITES DOS ON FIRST
; TWO TRACKS OF DISK
;
PUTDOS   LDA FRSTBOOT+1
         SEC 
         SBC USRBUF+1
         STA NSECSRW
         LDA FRSTBOOT+1
         STA USRBUF+1
         DEC USRBUF+1
         LDA #2
         STA TNUM
         LDA #4
         STA SNUM
         LDA #2
         STA CMDCODE
         JSR RWPAGES
         LDA FRSTBOOT+1
         STA FRSTPAG
         CLC 
         ADC #9
         STA USRBUF+1
         LDA #$A
         STA NSECSRW
         SEC 
         SBC #$1
         STA NUMSECS
         STA SNUM
         JSR RWPAGES
         RTS 
         DFS 6
RWPAGES  LDA RWTSPPTR+1
         LDY RWTSPPTR
         JSR CALLRWTS
         LDY SNUM
         DEY 
         BPL >8
         LDY #$F
         NOP 
         NOP 
         DEC TNUM
^8       STY SNUM
         DEC USRBUF+1
         DEC NSECSRW
         BNE RWPAGES
         RTS 
CALLRWTS PHP 
         SEI 
         JSR RWTSENT
         BCS >9
         PLP 
         CLC 
         RTS 
^9       PLP 
         SEC 
         RTS 
RWTSPRMS LDA SUBCODE
         STA USRBUF+1
         LDA #0
         STA USRBUF
         LDA VOLNUMBR
         EOR #$FF
         STA VOLEXPT
         RTS 
ZEROBUFR LDA #0
         TAY 
^0       STA (BUFADR),Y
         INY 
         BNE <0
         RTS 
         HEX 00
NUMPGS   HEX 1B
NSECSRW  HEX 000A1B
RWTSPPTR ADR $B7E8
FRSTBOOT ADR $B600
TBLTYPE  HEX 01
SNUM16   HEX 60
DNUM     HEX 01
VOLEXPT  HEX FF
TNUM     HEX 0C
SNUM     HEX 08FBB7
USRBUF   ADR $9600
BYTCNT   ADR $100
CMDCODE  HEX 02
ERRRCODE HEX 07
VOLFND   HEX FE
SLOTFND  HEX 60
DRVFND   HEX 01
UNUSED   HEX 00000001EFD800
         END 

